<template>
  <div class="flv-player"
       ref="ruienVideoPlayer"
       :style="fixedStyle"
       v-loading="loading">
    <video :id='videoId'
           style="display:none"
           class="flv-vidoe"
           controls></video>
    <div class="flv-video-box"
         @mousemove.capture="showControls"
         @mouseout.capture="hideControls">
      <canvas :id="canvasId"
              :width="boxWidth"
              :height="boxHeight"></canvas>
      <!-- 视频控件 -->
      <transition name="fade">
        <div class="controls"
             ref="controls"
             v-show="controlsShow">
          <canvas class="controls-bar"
                  :width="boxWidth"
                  height="30"
                  ref="controlsCanvas"></canvas>
          <div class="time-text"
               v-show="showTime"
               :style="`left:${timeTextLeft}px`">{{time}}</div>

          <div class="time-content"
               v-show="controlsShow"
               :style="`left:${timeContentLeft}px`">
            <div></div>
            <div class="margin-left-5 time-content-text">{{timeContent}}</div>
          </div>
        </div>
      </transition>
    </div>
    <div class="black-box"
         v-show="showBlack"></div>
  </div>
</template>

<script>
import { mapState } from 'vuex'
import axios from 'axios'
import mpegts from 'mpegts.js'
import screenfull from 'screenfull'
// eslint-disable-next-line no-unused-vars
import Canvas from './js/canvas'
const elementResizeDetectorMaker = require('element-resize-detector')
export default {
  props: {
    url: {
      type: String,
      default: ''
    }
  },
  mounted () {
    this.videoId = `video-${this.uuid()}`
    this.canvasId = `canvas-${this.uuid()}`
    this.$nextTick(() => {
      const erd = elementResizeDetectorMaker()
      this.erd = erd
      erd.listenTo(this.$refs.ruienVideoPlayer, this.setVideoCanvasSize)
    })
  },
  beforeDestroy () {
    this.erd.removeListener(this.$refs.ruienVideoPlayer, this.setVideoCanvasSize)
    this.reset()
  },
  data () {
    return {
      activeSec: 0,
      showBlack: true,
      controlsTimer: 0,
      timeTextLeft: 0,
      timeContentLeft: 0,
      controlsBarWidth: '500',
      loading: true,
      time: '00:00',
      timeContent: '00:00',
      showTime: false,
      boxHeight: 300,
      boxWidth: 500,
      controlsShow: false,
      videoId: '',
      canvasId: '',
      player: null,
      timer: 0,
      vidoeEl: '',
      erd: '',
      requestAnimationFrameTimer: 0,
      fixedStyle: {
        'position': 'relative',
        'z-index': 0
      }
    }
  },
  watch: {
    url (newValue) {
      if (newValue === '') {
        this.reset()
        return false
      }
      this.initVideo()
    },
    sidebarFold () {
      setTimeout(() => {
        this.drawControls()
        this.moveControlsPoint(this.activeSec)
      }, 500)
    }
  },
  computed: {
    ...mapState({
      sidebarFold: state => state.sidebarFold
    })
  },
  methods: {
    uuid () {
      let s = []
      let hexDigits = '0123456789abcdef'
      for (let i = 0; i < 36; i++) {
        s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1)
      }
      s[14] = '4'
      s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1)
      s[8] = s[13] = s[18] = s[23] = '-'

      let uuid = s.join('')
      return uuid
    },
    initVideo () {
      this.showBlack = false
      this.reset()
      const element = document.getElementById(this.videoId)
      const ruienVideoPlayerRef = this.$refs.ruienVideoPlayer
      this.boxHeight = ruienVideoPlayerRef.clientHeight
      this.boxWidth = ruienVideoPlayerRef.clientWidth
      element.volume = 0

      // 生成进度条
      this.drawControls()

      const player = mpegts.createPlayer({
        type: 'mse',
        url: this.url
      }, {
        isLive: true,
        liveBufferLatencyChasing: true,
        withCredentials: false,
        enableWorker: true,
        lazyLoadMaxDuration: 3 * 60,
        seekType: 'range'
      })

      player.attachMediaElement(element)
      player.load()
      element.addEventListener('loadeddata', this.loadeddataFn)
      element.addEventListener('canplay', this.canplayFn)
      // element.addEventListener('progress', (event) => {
      //   console.log(element.currentTime)
      //   this.moveControlsPoint(element.currentTime)
      // })
      // player.on(mpegts.Events.MEDIA_INFO, (event) => {
      //   console.log(event)
      // })
      this.player = player
      this.vidoeEl = element
    },
    // 移动播放点
    moveControlsPoint (num) {
      const itemWidth = this.boxWidth / 3600
      this.timeContent = this.formatDate(num).replace(/_/g, ':')
      this.timeContentLeft = itemWidth * num
      // this.controlsBarTimer = setTimeout(() => {
      //   num++
      //   this.moveControlsPoint(num)
      // }, 1000)
    },
    mouseoutControlsBar () {
      this.showTime = false
    },
    // 绘制进度条
    drawControls () {
      const canvasEl = this.$refs.controlsCanvas
      const canvas = new Canvas(canvasEl)
      canvas.clearRect(0, 0, this.boxWidth, 30)
      canvasEl.removeEventListener('mouseout', this.mouseoutControlsBar)
      canvasEl.addEventListener('mouseout', this.mouseoutControlsBar)
      const itemWidth = this.boxWidth / 3600
      for (let index = 0; index < 3600; index++) {
        const rect = canvas.rect({
          x: itemWidth * (index + 1),
          y: 0,
          width: itemWidth,
          height: 30,
          fillStyle: '#67C23A'
        })

        rect.on('mousemove', this.rectMousemove)

        rect.on('click', this.rectClick)
      }

      canvas.draw()
    },
    rectClick (event, num) {
      this.timeContent = this.formatDate(num).replace(/_/g, ':')
      this.timeContentLeft = event.offsetX
      this.activeSec = num
      this.$emit('selectTime', this.formatDate(num))
    },
    rectMousemove (event, num) {
      this.showTime = true
      const time = this.formatDate(num)
      this.timeTextLeft = event.offsetX
      this.time = time.replace(/_/g, ':')
      this.$emit('moveTime', time)
    },
    test (millisecond) {
      if (millisecond <= 0) {
        return '00:00'
      }
      const h_ = Math.floor(millisecond / 3600000)
      const m_ = Math.floor(millisecond / 60000)
      const s_ = Math.floor(millisecond / 1000)
      const h = h_ > 9 ? h_.toFixed() : `0${h_.toFixed()}`
      const m = m_ > 9 ? m_.toFixed() : `0${m_.toFixed()}`
      const s = s_ > 9 ? s_.toFixed() : `0${s_.toFixed()}`

      if (h > 0) {
        return `${h}:${m >= 60 ? '00' : m}:${s >= 60 ? '00' : s}`
      }
      return `${m >= 60 ? '00' : m}:${s >= 60 ? '00' : s}`
    },
    // TODO 格式化时间
    formatDate (sec) {
      if (sec <= 0) {
        return '00:00'
      }
      const h_ = Math.floor(sec / 3600)
      const m_ = Math.floor(sec / 60)
      const s_ = sec % 60
      const h = h_ > 9 ? h_.toFixed() : `0${h_.toFixed()}`
      const m = m_ > 9 ? m_.toFixed() : `0${m_.toFixed()}`
      const s = s_ > 9 ? s_.toFixed() : `0${s_.toFixed()}`

      if (h > 0) {
        return `${h}_${m >= 60 ? '00' : m}_${s >= 60 ? '00' : s}`
      }
      return `${m >= 60 ? '00' : m}_${s >= 60 ? '00' : s}`
    },
    // 监听开始播放的第一帧
    loadeddataFn () {
      this.loading = false
      this.player.play()
      this.videoMappingCanvas()
      this.$emit('loadeddataFn')
      // this.moveControlsPoint(0)
    },
    // 缓冲完成
    canplayFn () {
      // this.moveControlsPoint(this.vidoeEl.currentTime)
    },
    // 将视频内容转到画布上
    videoMappingCanvas () {
      const videoCanvasRef = document.getElementById(this.canvasId)
      this.ctx = videoCanvasRef.getContext('2d')
      this.ctx.drawImage(this.player._mediaElement, 0, 0, this.boxWidth, this.boxHeight)
      this.requestAnimationFrameTimer = requestAnimationFrame(this.videoMappingCanvas)
    },
    // TODO 全屏
    fullscreenHandle () {
      if (!screenfull.isFullscreen) {
        clearTimeout(this.timer)
        screenfull.toggle().then(() => {
          this.fixedStyle = {
            'position': 'fixed',
            'z-index': 99999999
          }
          this.timer = setTimeout(() => {
            clearTimeout(this.timer)
          }, 100)
        })
      } else {
        screenfull.exit().then(() => {
          this.fixedStyle = {
            'position': 'relative',
            'z-index': 0
          }
        })
      }
    },
    // TODO 关闭全屏
    beforeClose () {
      this.fixedStyle = {
        position: 'relative'
      }
      if (screenfull.isFullscreen) {
        screenfull.exit()
      }
    },
    // TODO 监听是否为全屏状态
    monitorFullScreen () {
      if (screenfull.isEnabled) {
        screenfull.on('change', () => {
          if (!screenfull.isFullscreen) {
            this.beforeClose()
          }
        })
      }
    },
    // TODO 设置视频画布的大小
    setVideoCanvasSize (el) {
      const width = el.clientWidth
      const height = el.clientHeight
      this.boxWidth = width
      this.boxHeight = height
    },
    // TODO 显示控件
    showControls () {
      clearTimeout(this.controlsTimer)
      this.controlsShow = true
    },
    // TODO 隐藏控件
    hideControls () {
      clearTimeout(this.controlsTimer)
      this.controlsTimer = setTimeout(() => {
        this.controlsShow = false
      }, 300)
    },
    // 重置播放器
    reset () {
      if (typeof this.player !== 'undefined') {
        if (this.player !== null) {
          this.loading = true
          cancelAnimationFrame(this.requestAnimationFrameTimer)
          this.vidoeEl.removeEventListener('loadeddata', this.loadeddataFn)
          this.vidoeEl.removeEventListener('canplay', this.canplayFn)
          this.player.pause()
          this.player.unload()
          this.player.detachMediaElement()
          this.player.destroy()
          this.player = null
        }
      }
    },
    // TODO url 转 blob连接
    async getBlobUrl (url) {
      const res = await axios.get(url, {
        responseType: 'blob'
      })
      return res || { data: -1 }
    }
  }
}
</script>

<style lang="scss" scoped>
.flv-vidoe {
  position: absolute;
  top: 0;
  left: 0;
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
  opacity: 0;
}
.flv-player {
  width: 100%;
  height: 100%;
  position: relative;
  top: 0;
  left: 0;

  .black-box {
    width: 100%;
    height: 100%;
    position: absolute;
    top: 0;
    left: 0;
    background-color: #333;
    z-index: 2999;
  }
  .flv-video-box {
    position: relative;
    display: inline-block;
    .controls {
      position: absolute;
      bottom: 0;
      left: 0;
      width: 100%;
      background-color: rgba(19, 19, 19, 0.6);
      color: white;
      // background: linear-gradient(to top, #050505, transparent);
      text-align: left;
      margin-left: auto;
      margin-right: auto;
      z-index: 2;
      .controls-bar {
        cursor: pointer;
      }
      .time-text {
        position: absolute;
        top: -25px;
        left: 0;
        color: #67c23a;
      }
      .time-content {
        width: 5px;
        height: 30px;
        // background-color: #409eff;
        display: flex;
        align-content: center;
        position: absolute;
        top: 0;
        left: 0;
        color: transparent;
        .time-content-text {
          position: absolute;
          top: -14px;
          left: -5px;
        }
      }
      // .controls-btn {
      //   width: 100%;
      //   height: 30px;
      //   display: flex;
      //   justify-content: space-between;
      //   align-items: center;
      //   background-color: white;
      //   .second-item {
      //     flex: 1;
      //     height: 30px;
      //     background-color: aquamarine;
      //   }
      // }
    }
  }
}
</style>
